import { Color, Group, Material, Mesh, Object3D, Object3DEventMap } from 'three';

export abstract class Helper {
    static deepClone(object: Object3D<Object3DEventMap>) {
        let target = new Object3D();
        if (object.type === 'Mesh' || object.type === 'Sprite') {
            const mesh = (object as Mesh)
            let newMaterial: Material | Material[] = []
            if (Array.isArray(mesh.material)) {
                newMaterial = mesh.material.map(i => { return i.clone() })
            } else {
                newMaterial = mesh.material.clone()
            }
            target = new Mesh((object as Mesh).geometry.clone(), newMaterial);
        } else {
            target = object.clone(false);
        }

        target.name = object.name;
        copyProperty(target, object);

        if (object.children && object.children.length > 0) {

            object.children.forEach(child => {
                target.add(this.deepClone(child));
            });
        }


        return target;

    }

    static getHexColorStr(color: Color) {
        return `#${color.getHexString()}`
    }

    static cloneObject(obj: object) {
        return JSON.parse(JSON.stringify(obj))
    }




    // 设置Group对象及其子对象的透明度
    static setGroupOpacity(group: Group, opacity: number) {
        group.traverse((object: Object3D) => {
            if (object.type === 'Mesh') {
                // 如果是Mesh对象，设置其材质的透明度
                this.setMeshMaterialOpacity(object as Mesh, opacity)
            }
        });
    }

    static setMeshMaterialOpacity(mesh: Mesh, opacity: number) {
        if (Array.isArray(mesh.material)) {
            mesh.material.map(i => {
                i.opacity = opacity
                i.transparent = (opacity < 1)
            })
        } else {
            mesh.material.opacity = opacity
            mesh.material.transparent = (opacity < 1)
        }
    }

    static findRootGroupID(child: Object3D) {
        let parent = child.parent
        let lastParentID = null
        while (parent && !(parent.type === 'Scene')) {
            lastParentID = parent.id
            parent = parent.parent
        }
        return lastParentID;
    }



    static getNameWithPrefix(prefix: string, name: string) {
        return `${prefix}__${name}`
    }

    static setY(mesh: Mesh) {
        mesh.geometry.computeBoundingBox()
        mesh.position.y = Math.abs(mesh.geometry.boundingBox!.min.y)
    }
}

function copyProperty(target: Object3D, source: Object3D) {

    target.position.x = source.position.x;
    target.position.y = source.position.y;
    target.position.z = source.position.z;

    target.rotation.x = source.rotation.x;
    target.rotation.y = source.rotation.y;
    target.rotation.z = source.rotation.z;

    target.scale.x = source.scale.x;
    target.scale.y = source.scale.y;
    target.scale.z = source.scale.z;
}

